import algos.*;
import java.io.*;
import java.util.*;
import utils.Pair;

import static utils.Common.*;

@SuppressWarnings("unchecked")
public class Test {
    
    private static boolean isWord(String s) {
        return Vocabulary.isWord(s);
    }

    private static List<String[]> readSentence(String s) {
        List<String[]> answer = newArrayList();
        StringTokenizer st = new StringTokenizer(s);
        List<String> words = newArrayList();
        while (st.hasMoreTokens()) {
            String token = st.nextToken().trim().toLowerCase();
            if (isWord(token)) words.add(token);
        }
        for (int i = 0, n = words.size(); i + 4 < n; i++) {
            String[] array = new String[4];
            for (int j = 0; j < 4; j++) {
                array[j] = words.get(i + j);
            }
            answer.add(array);
        }
        return answer;
    }

    private static List<String[]> readBook(String filename) {
        try {
            BufferedReader br = null;
            try {
                br = new BufferedReader(new FileReader(filename));
                String text = "";
                while (true) {
                    String tmp = br.readLine();
                    if (tmp == null) break;
                    text = text + tmp + " ";
                }
                List<String[]> answer = newArrayList();
                int r = -1;
                while (r < text.length()) {
                    int e = text.indexOf('.', r + 1);
                    if (e == -1) e = text.length();
                    answer.addAll(readSentence(text.substring(Math.max(0, r), e)));
                    r = e;
                }
                return answer;
            } finally {
                if (br != null) br.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void main(String[] args) {
        List<String> ngf2 = newArrayList();
        ngf2.add("1grams/out");
        ngf2.add("2grams/out");
        ngf2.add("3grams/out");
        UserEngine engine = UserEngine.create(ngf2);
        List<Double> coreCoefs = newArrayList();
        List<Double> userCoefs = newArrayList();
        coreCoefs.add(0.000000000001);
        coreCoefs.add(0.0000001);
        coreCoefs.add(0.499999899999);
        userCoefs.add(0.0);
        userCoefs.add(0.0);
        userCoefs.add(0.5);
        engine.setCoefs(coreCoefs, userCoefs);
        /*
        List<Pair<String, Double>> ngf = newArrayList();
        ngf.add(makePair("1grams/out", 0.000000000001));
        ngf.add(makePair("2grams/out", 0.0000001));
        ngf.add(makePair("3grams/out", 0.999999899999));
        Engine engine = Engine.create(ngf);
        */
        System.out.println("engine created");
        List<String[]> book = readBook("book.txt");
        final int LETTERS_BEFORE_SUGGEST = 3;
        final int COLLECT_STATS = 10;
        int[] guessed = new int[COLLECT_STATS];
        int all = 0;
        for (String[] array : book) {
            final int n = array.length;
            List<String> words = newArrayList(n - 1);
            for (int i = 0; i < n - 1; i++) {
                words.add(array[i]);
            }
            final String last = array[n - 1];
            if (last.length() < LETTERS_BEFORE_SUGGEST + 1) continue;
            String prefix = "";
            for (int i = 0; i < LETTERS_BEFORE_SUGGEST; i++) {
                prefix += last.charAt(i);
            }
            List<Pair<Double, String>> suggestion = engine.get(words, prefix, 0);
            for (int i = 0; i < COLLECT_STATS && i < suggestion.size(); i++) {
                if (suggestion.get(i).second.equals(last)) {
                    guessed[i]++;
                }
            }
            all++;
        }
        System.out.println(all + " tests");
        for (int i = 0; i < COLLECT_STATS; i++) {
            System.out.println(i + ": " + guessed[i] + " hits");
        }
        System.out.println("1st place hits: " + (guessed[0] * 1. / all));
        int three = 0;
        for (int i = 0; i < 3; i++) {
            three += guessed[i];
        }
        System.out.println("1st-3rd place hits: " + (three * 1. / all));
        




        int LENGTHS = 15;
        List<Integer>[] lens = new ArrayList[LENGTHS];
        for (int i = 0; i < LENGTHS; i++) lens[i] = newArrayList();
        all = 0;
        for (String[] array : book) {
            all++;
            if (all == 1000) break;
            final int n = array.length;
            List<String> words = newArrayList(n - 1);
            for (int i = 0; i < n - 1; i++) {
                words.add(array[i]);
            }
            final String last = array[n - 1];
            int len = last.length();
            if (len >= LENGTHS) continue;
            int l = 0, r = len;
            while (l < r) {
                int m = (l + r) / 2;
                String prefix = last.substring(0, m);
                List<Pair<Double, String>> sugg = engine.get(words, prefix, 0);
                if (sugg.isEmpty() || !sugg.get(0).second.equals(last))
                    l = m + 1;
                else r = m;
            }
            lens[len].add(l);
        }
        System.out.println();
        System.out.println(all + " tests");
        System.out.println("Average number of hits to type a word of length:");
        for (int i = 1; i < LENGTHS; i++) {
            long sum = 0;
            for (int x : lens[i]) sum += x;
            System.out.print(i + " letters: ");
            if (lens[i].isEmpty()) System.out.println("N/A");
                else System.out.println(sum * 1. / lens[i].size());
        }
    }

}

